#include "Displayer.h"
#include "ui_Displayer.h"
#include <QPainter>
#include <QStyleOption>
#include <QStyle>
#include <QMouseEvent>
#include "CDicomImage.h"
#include "Utilities.h"

Displayer::Displayer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Displayer)
{
    ui->setupUi(this);

    connect(&m_drawParam, &DrawParam::negativeChanged, this, [=](){
        this->update();
    });

    connect(&m_drawParam, &DrawParam::curWindowChanged, this, [=](){
        int w, h;
        m_pImage->CreateDIB(m_pDib, w, h, m_drawParam.getCurWL(), m_drawParam.getCurWW());
        this->update();
    });

    connect(&m_drawParam, &DrawParam::transformChanged, this, [=](){
        this->update();
    });

    connect(&m_drawParam, &DrawParam::frameChanged, this, [=](){
        int w, h;
        m_pImage->CreateDIB(m_pDib, w, h, m_drawParam.getCurWL(), m_drawParam.getCurWW(), m_drawParam.getFrame());
        this->update();
    });


//    connect(&m_drawParam, &DrawParam::angleChanged, this, [=](){
//        qDebug() << "DrawInfo::angleChanged, angle:" << this->m_drawParam.getAngle();
//         this->update();
//    });
}

Displayer::~Displayer()
{
    delete ui;
}

bool Displayer::LoadFile(QString fn)
{
    CDicomImage* pImg = new CDicomImage();
    std::string dcmFn = fn.toStdString();
    if (!pImg->ParseFile(dcmFn)) {
        delete pImg;
        pImg = nullptr;
        return false;
    }

    SetImage(static_cast<CBaseImage*>(pImg));

    return true;
}

void Displayer::SetImage(CBaseImage *pImg)
{
    if (pImg==nullptr) return;
    m_pImage = pImg;
    int w, h;
    double wl, ww;
    m_pImage->GetDefaultWindow(wl, ww);
    m_pImage->CreateDIB(m_pDib, w, h, wl, ww);

    m_drawParam.setFrame(0);
    m_drawParam.setSize(w, h);
    m_drawParam.initWindow(wl, ww);
    m_drawParam.initTransform(rect());
//    m_drawParam.addFlip(2);

    this->update();
}

bool Displayer::isLoaded()
{
    return (m_pDib != nullptr);
}

void Displayer::PrevFrame()
{
    if (m_drawParam.getFrame() == 0) {
        return;
    }

    m_drawParam.setFrame(m_drawParam.getFrame() - 1);
}

void Displayer::NextFrame()
{
    int count = m_pImage->GetFrameCount();
    if (m_drawParam.getFrame() >= count - 1) {
        return;
    }

    m_drawParam.setFrame(m_drawParam.getFrame() + 1);
}

bool Displayer::Export(std::string dst, int format)
{
    if (m_pImage == nullptr) return false;
    return m_pImage->Export(dst, format);
}

void Displayer::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    p.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);

    QStyleOption opt;
    opt.init(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

//    QRect rc = this->rect();

    // 图像
    if (isLoaded())
    {
        QImage qImg((uchar*)m_pDib, m_drawParam.getWidth(), m_drawParam.getHeight(), QImage::Format_BGR888);

        m_pix = QPixmap::fromImage(qImg);
        m_pix = m_pix.transformed(m_drawParam.getImgTrans());

        p.setTransform(m_drawParam.getTransform());

        // 图像
        p.drawPixmap(QPoint(0, 0), m_pix);

        p.resetTransform();

        drawText(p);
    }
}

void Displayer::resizeEvent(QResizeEvent *)
{
    if (m_pDib) {
        m_drawParam.initTransform(rect());
        update();
    }
}

void Displayer::mousePressEvent(QMouseEvent *event)
{
    QPixmap pix;
    if (event->button() == Qt::LeftButton) {
        m_action = MA_Window;
        m_lastPos = event->pos();

        pix = QPixmap(":/res/window.png");
    }
    else if (event->button() == Qt::MiddleButton) {
        m_action = MA_Pan;
        m_lastPos = event->pos();

        pix = QPixmap(":/res/move.png");
    }
    else if (event->button() == Qt::RightButton) {
        m_action = MA_Scale;
        m_lastPos = event->pos();

        pix = QPixmap(":/res/scale.png");
    }

    this->setCursor(QCursor(pix));
}

void Displayer::mouseReleaseEvent(QMouseEvent *event)
{
    m_action = MA_None;
    this->setCursor(Qt::ArrowCursor);
}

void Displayer::mouseMoveEvent(QMouseEvent *event)
{
    QPoint pos = event->pos();
//    qDebug() << "mouse move pos:" << pos;

    int dx, dy;
    dx = pos.x() - m_lastPos.x();
    dy = pos.y() - m_lastPos.y();

    m_lastPos = pos;

    if (m_action == MA_Window) {
        double minVal, maxVal;
        m_pImage->GetRange(minVal, maxVal);
        double deltaWW = (maxVal - minVal) / 1024 * dx;
        double deltaWC = (maxVal - minVal) / 1024 * dy;
        m_drawParam.adjustWindow(deltaWW, deltaWC);
    } else if (m_action == MA_Pan) {
        m_drawParam.addTranslate(dx, dy);
    } else if (m_action == MA_Scale) {
        if (abs(dy) > 0) {
            double delta = dy/abs(dy) * 0.02;
            m_drawParam.addScale(delta);
        }

    }

}

void Displayer::wheelEvent(QWheelEvent *event)
{
    int delta = event->delta();
    int frames = m_pImage->GetFrameCount();

    if (frames > 1) {
        if (delta > 0) { // 上一帧
            PrevFrame();
        } else { // 下一帧
            NextFrame();
        }
    }

}

void Displayer::drawText(QPainter& p)
{
    QRect rc = rect();

    QFont font;
    font.setFamily("Microsoft YaHei");
    font.setPixelSize(16);

    p.setFont(font);
    p.setPen(QColor(255, 255, 255));

    QFontMetrics fm(font);
    QRect bound;

    QPoint pt(2, 18);
    int txtH = 18;

    // 左上角
    QString qText;
    std::string txt, tmp;
    txt = m_pImage->GetPatientInfo().patName;
    if (m_pImage->GetPatientInfo().sex != "") {
        txt += " / " + m_pImage->GetPatientInfo().sex;
    }

    if (m_pImage->GetPatientInfo().studyAge != "") {
        txt += " / " + m_pImage->GetPatientInfo().studyAge;
    }

    qText = QString::fromLocal8Bit(txt.c_str());
    p.drawText(pt, qText);
    pt.ry() += txtH;

    if (m_pImage->GetStudyInfo().studyId != "") {
        txt = m_pImage->GetStudyInfo().studyId;
        qText = QString::fromLocal8Bit(txt.c_str());
        p.drawText(pt, qText);
        pt.ry() += txtH;
    }


    // 右上角
    pt.ry() = 18;
    FormatStr(txt, "WL: %.1f WW: %.1f", m_drawParam.getCurWL(), m_drawParam.getCurWW());
    qText = QString::fromLocal8Bit(txt.c_str());
    bound = fm.boundingRect(qText);
    pt.rx() = rc.right() - bound.width() - 2;
    p.drawText(pt, qText);
    pt.ry() += txtH;

    int nFrames = m_pImage->GetFrameCount();
    if (nFrames > 1) {
        qText = QString("fr: %1/%2").arg(m_drawParam.getFrame() + 1).arg(nFrames);
        bound = fm.boundingRect(qText);
        pt.rx() = rc.right() - bound.width() - 2;
        p.drawText(pt, qText);
        pt.ry() += txtH;
    }

    // 左下角
    pt.rx() = 2;
    pt.ry() = rc.bottom() - 4;

    if (m_pImage->GetStudyInfo().hospitalName != "") {
        txt = m_pImage->GetStudyInfo().hospitalName;
        qText = QString::fromLocal8Bit(txt.c_str());
        p.drawText(pt, qText);
        pt.ry() -= txtH;
    }

    if (m_pImage->GetSeriesInfo().seriesDate != "") {
        txt = m_pImage->GetSeriesInfo().seriesDate;
        if (m_pImage->GetSeriesInfo().seriesTime != "") {
            txt += " " + m_pImage->GetSeriesInfo().seriesTime;
        }
        qText = QString::fromLocal8Bit(txt.c_str());
        p.drawText(pt, qText);
        pt.ry() -= txtH;
    }

    if (m_pImage->GetSeriesInfo().seriesDesc != "") {
        txt = m_pImage->GetSeriesInfo().seriesDesc;
        qText = QString::fromLocal8Bit(txt.c_str());
        p.drawText(pt, qText);
        pt.ry() -= txtH;
    }

    if (m_pImage->GetStudyInfo().modality != "") {
        txt = m_pImage->GetStudyInfo().modality;
        qText = QString::fromLocal8Bit(txt.c_str());
        p.drawText(pt, qText);
        pt.ry() -= txtH;
    }

    // 右下角
    pt.ry() = rc.bottom() - 4;

    txt = "";
    tmp = m_pImage->GetImageInfo().sliceThickness;
    if (!tmp.empty()) {
        txt = "T:" + tmp;
    }

    tmp = m_pImage->GetImageInfo().sliceLocation;
    if (!tmp.empty()) {
        if (!txt.empty()) txt += " ";
        double location = atof(tmp.c_str());
        FormatStr(tmp, "%.1f", location);
        txt += "L:" + tmp;
    }

    if (!txt.empty()) {
        qText = QString::fromLocal8Bit(txt.c_str());
        bound = fm.boundingRect(qText);
        pt.rx() = rc.right() - bound.width() - 2;
        p.drawText(pt, qText);
        pt.ry() -= txtH;
    }


    FormatStr(txt, "Zoom: %.2f", m_drawParam.getZoom());
    qText = QString::fromLocal8Bit(txt.c_str());
    bound = fm.boundingRect(qText);
    pt.rx() = rc.right() - bound.width() - 2;
    p.drawText(pt, qText);

}
